package com.tanhua.server.service;

import com.alibaba.fastjson.JSON;
import com.tanhua.commons.templates.AipFaceTemplate;
import com.tanhua.commons.templates.HuanXinTemplate;
import com.tanhua.commons.templates.OssTemplate;
import com.tanhua.commons.templates.SmsTemplate;
import com.tanhua.domain.db.User;
import com.tanhua.domain.db.UserInfo;
import com.tanhua.domain.mongo.UserLike;
import com.tanhua.domain.vo.ErrorResult;
import com.tanhua.domain.vo.PageResult;
import com.tanhua.domain.vo.UserInfoVo;
import com.tanhua.domain.vo.UserLikeVo;
import com.tanhua.dubbo.api.FriendApi;
import com.tanhua.dubbo.api.UserApi;
import com.tanhua.dubbo.api.UserInfoApi;
import com.tanhua.dubbo.api.mongo.UserLikeApi;
import com.tanhua.server.Interceptor.UserHolder;
import com.tanhua.server.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.bson.types.ObjectId;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.util.*;

@Service
@Slf4j
public class UserService {

    @Reference
    private UserApi userApi;


    @Reference
    private UserInfoApi userInfoApi;

    @Autowired
    private SmsTemplate smsTemplate;

    @Autowired
    private HuanXinTemplate huanXinTemplate;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    private static final String SMS_KEY = "SMS_KEY_";

    private static final String TOKEN_KEY = "TOKEN_KEY_";

    @Autowired
    private AipFaceTemplate aipFaceTemplate;

    @Autowired
    private OssTemplate ossTemplate;

    @Value("${tanhua.secret}")
    private String secret;


    @Reference
    private UserLikeApi userLikeApi;

    @Reference
    private FriendApi friendApi;
    //登录的key
    private static final String freezingLogin = "userFreezing_login_";
    @Autowired(required = false)
    private RocketMQTemplate rocketMQTemplate;


    public ResponseEntity<Object> findByMobile(String mobile) {
        try {
            User user = userApi.findByMobile(mobile);
            return ResponseEntity.ok(user);
        } catch (Exception e) {
            e.printStackTrace();
            Map<String, String> param = new HashMap<>();
            param.put("errorCode", "100");
            param.put("errorMsg", "该手机号不存在");
            return ResponseEntity.status(500).body(param);
        }
    }


    /**
     * 作用： 保存用户
     *
     * @param user
     * @return
     */
    public ResponseEntity<Object> save(User user) {//如果是json字符串过来，那么必须是post请求
        long userId = userApi.save(user);
        return ResponseEntity.ok(userId);
    }

    /**
     * 发送短信验证码
     *
     * @param phone
     * @return
     */
    public ResponseEntity<Object> sendSms(String phone) {

        User user = (User) findByMobile(phone).getBody();
        Boolean b = redisTemplate.hasKey(freezingLogin + user.getId());

        if(b!=null) {
            if (b) {
                return ResponseEntity.status(401).body(ErrorResult.freezingError());
            }
        }
        //1. 生成6位验证码
        String code = "123456";// RandomStringUtils.randomNumeric(6);

        //2. 发送验证码
        log.info("=======本次验证码：======>" + code);
//        smsTemplate.sendSms(phone,code);

        //3. 验证码存储起来，验证码存储到redis中，有效时间5分钟
        String key = SMS_KEY + phone;
        redisTemplate.opsForValue().set(key, code, Duration.ofMinutes(5));


        //4. 返回响应
        return ResponseEntity.ok(null);


    }

    /**
     * 验证登陆
     *
     * @param phone
     * @param verificationCode
     * @return
     */
    public ResponseEntity<Object> loginVerification(String phone, String verificationCode) {
//        1. 取出验证码并且对比验证码
        String key = SMS_KEY + phone;
        String authCode = redisTemplate.opsForValue().get(key);
        if (authCode == null || !authCode.equals(verificationCode)) {
           /* Map<String,String> map = new HashMap();
            map.put("errCode","xxx");
            map.put("errMessage","xxx");*/
            return ResponseEntity.status(401).body(ErrorResult.fail());
        }
//        2. 删除验证码
        redisTemplate.delete(key);
//        3. 根据手机号查找用户
        User user = userApi.findByMobile(phone);
//        4. 如果查找到的用户为空，则注册新用户
        boolean isNew = false; //默认不是新用户
        //用户的操作行为
        String type = "0101"; //默认是登陆行为
        if (user == null) {
            //该用户是一个新用户
            user = new User();
            user.setMobile(phone);
            user.setPassword("123");

            long userId = userApi.save(user);
            user.setId(userId);
            isNew = true;
            //如果是新的用户，注册完毕之后我们需要吧该用户注册到环信上
            huanXinTemplate.register(userId);
            type = "0102";//注册行为
        }
        //前后端都是网页形式，以前我们使用登陆成功标记我们记录在哪里？session


        //封装消息发送到rocketmq
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("userId", user.getId());
        paramMap.put("type", type);
        paramMap.put("date", new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
        //发送消息

        rocketMQTemplate.convertAndSend("tanhua-log", JSON.toJSONString(paramMap));

//        5. 根据接口的需求返回响应
        String token = JwtUtils.createToken(user.getId(), phone, secret);
        //把用户的信息存储到Redis中
        String userJson = JSON.toJSONString(user);
        String tokenKey = TOKEN_KEY + token;
        //默认4个小时过期
        redisTemplate.opsForValue().set(tokenKey, userJson, Duration.ofHours(4));

        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("token", token);
        resultMap.put("isNew", isNew);
        return ResponseEntity.ok(resultMap);
    }

    //保存用户个人信息
    public ResponseEntity<Object> saveUserInfo(UserInfo userInfo, String token) {
        //1.根据token查找到登陆的用户
        User user = findUserByToken(token);

        //2.判断是否可以查找到用户
        if (user == null) {
            return ResponseEntity.status(401).body(ErrorResult.error());
        }

        //3.设置的用户信息的id和User的id一样
        userInfo.setId(user.getId());

        //4. 保存信息
        userInfoApi.saveUserInfo(userInfo);

        //5. 返回响应
        return ResponseEntity.ok(null);
    }

    //根据token得到用户
    public User findUserByToken(String token) {
        String tokenKey = TOKEN_KEY + token;
        String userJson = redisTemplate.opsForValue().get(tokenKey);
        if (userJson == null) {
            //这个token查找不到登录用户
            return null;
        }
        User user = JSON.parseObject(userJson, User.class);
        return user;
    }

    //更新头像
    public ResponseEntity<Object> updateHeader(MultipartFile headPhoto, String token) throws IOException {
        //1.根据token查找到登陆的用户
        User user = UserHolder.get();

        //3. 识别是否为人
        boolean isFace = aipFaceTemplate.detect(headPhoto.getBytes());

        //4. 如果是人脸，上传,得到图片的url
        String headImageUrl = null;
        if (isFace) {
            headImageUrl = ossTemplate.upload(headPhoto.getOriginalFilename(), headPhoto.getInputStream());
        }

        //5. 更新用户的头像
        UserInfo userInfo = new UserInfo();
        userInfo.setId(user.getId());
        userInfo.setAvatar(headImageUrl);
        userInfoApi.update(userInfo);


        //6. 返回响应
        return ResponseEntity.ok(null);


    }


    public ResponseEntity findUserInfoById(Long userID, Long huanxinID) {
        //1.根据token查找到登陆的用户
        long userId = UserHolder.getUserId();//当前登陆者id
        if (userID != null) {
            userId = userID;
        } else if (huanxinID != null) {
            userId = huanxinID;
        }

        //3. 根据用户的id查找用户的信息
        UserInfo userInfo = userInfoApi.findById(userId);

        //4.创建Vo，并且把userInfo信息拷贝到vo中
        UserInfoVo userInfoVo = new UserInfoVo();
        BeanUtils.copyProperties(userInfo, userInfoVo);
        if (userInfo.getAge() != null) {
            userInfoVo.setAge(userInfo.getAge() + "");
        }
        return ResponseEntity.ok(userInfoVo);

    }

    //更新用户信息
    public ResponseEntity updateUserInfo(UserInfo userInfo, String token) {
        //1.根据token查找到登陆的用户
        User user = findUserByToken(token);

        //2.判断是否可以查找到用户
        if (user == null) {
            return ResponseEntity.status(401).body(ErrorResult.error());
        }
        //3. 把当前登录的id拷贝到UserInfo中
        userInfo.setId(user.getId());

        //4. 根据用户的id更新用户信息
        userInfoApi.update(userInfo);

        return ResponseEntity.ok(null);

    }


    //统计朋友、喜欢、粉丝数量
    public ResponseEntity queryCounts() {
        //1. 获取当前登陆者id
        long userId = UserHolder.getUserId();
        //2. 查询朋友数、喜欢数、粉丝数
        Long eachLoveCount = userLikeApi.queryEachLoveCount(userId); //朋友数
        Long loveCount = userLikeApi.queryLoveCount(userId); // 喜欢数
        Long fansCount = userLikeApi.queryFansCount(userId); //粉丝数


        Map<String, Integer> resultMap = new HashMap<>();
        resultMap.put("eachLoveCount", eachLoveCount.intValue());
        resultMap.put("loveCount", loveCount.intValue());
        resultMap.put("fanCount", fansCount.intValue());

        return ResponseEntity.ok(resultMap);
    }


    //互相喜欢、喜欢、粉丝、谁看过我 - 翻页列表

    /**
     * 1 互相关注
     * 2 我关注
     * 3 粉丝
     * 4 谁看过我
     *
     * @param type
     * @param page
     * @param pagesize
     * @return
     */
    public ResponseEntity queryUserLikeList(Integer type, Integer page, Integer pagesize) {
        //1. 获取当前的登陆者id
        long userId = UserHolder.getUserId();
        //2. 根据type判断目前查询的数据，得到一个PageResult，疑问： 请问pageREuslt的items存储的是什么对象？
        // 解决方案： 让所有的方法返回的pageReuslt存储的都是一个List<Map<String,Object>>  ，map对象中存储 ：用户的id，缘分值
        PageResult pageResult = null;
        switch (type) {
            case 1:  //操作的表 ： tanhua_users
                pageResult = userLikeApi.queryEachLove(page, pagesize, userId);//互相喜欢
                break;
            case 2:  // user_like
                pageResult = userLikeApi.queryLove(page, pagesize, userId);//我喜欢
                break;
            case 3:  // user_like
                pageResult = userLikeApi.queryFans(page, pagesize, userId);//我的粉丝
                break;
            case 4:  //visitors
                pageResult = userLikeApi.queryVisitors(page, pagesize, userId);//我的访客
                break;
        }
        //获取pageResult的item
        List<Map<String, Object>> listMap = (List<Map<String, Object>>) pageResult.getItems();
        List<UserLikeVo> voList = new ArrayList<>();
        for (Map<String, Object> map : listMap) {
            //取出map的数据
            Long uId = (Long) map.get("userId");
            Integer score = (Integer) map.get("score");
            //根据用户的id查找用户的信息
            UserInfo userInfo = userInfoApi.findById(uId);
            //把userInfo的信息封装到userLikeVo对象
            UserLikeVo vo = new UserLikeVo();
            //属性拷贝
            if (userInfo != null) {
                BeanUtils.copyProperties(userInfo, vo);
            }
            vo.setMatchRate(score);
            voList.add(vo);
        }
        //修改PageResult的items
        pageResult.setItems(voList);
        return ResponseEntity.ok(pageResult);


    }

    //让粉丝变好友
    public ResponseEntity fansLike(Long fansId) {
        //1. 删除粉丝的数据
        long userId = UserHolder.getUserId();
        userLikeApi.delete(userId, fansId);
        //2. 插入好友表的数据
        friendApi.save(userId, fansId.intValue());

        //3. 注册环信的好友数据
        huanXinTemplate.contactUsers(userId, fansId);

        return ResponseEntity.ok(null);
    }
    /**
     * 用户更改 手机号 操作redis校验验证码
     */
    public ResponseEntity<Object> checkVerificationCode(String mobile, String verificationCode) {
        Boolean verification = getVerificationCodeAndCheck(mobile, verificationCode);
        Map<String, Boolean> resultMap = new HashMap<>();
        resultMap.put("verification", verification);
        return ResponseEntity.ok(resultMap);
    }
    /**
     * 操作redis校验验证码
     */
    public Boolean getVerificationCodeAndCheck(String phone, String verificationCode) {
        // 从redis中获取验证码
        ValueOperations<String, String> ops = redisTemplate.opsForValue();
        String redisCode = ops.get(SMS_KEY + phone);
        //并校验验证码
        if (redisCode == null || !redisCode.equals(verificationCode)) {
            // 校验完毕，从redis中删除验证码
            redisTemplate.delete(SMS_KEY + phone);
            return false;
        } else {
            return true;
        }
    }
    /**
     * 更新用户的手机号
     */
    public ResponseEntity<Object> savePhone(String phone) {
        User user = userApi.findByMobile(phone);
        if (user != null) {
            return ResponseEntity.status(500).body(ErrorResult.mobileError());
        }
        user.setMobile(phone);
        userApi.upDataPhone(user);
        return ResponseEntity.ok(null);
    }

    /**
     * 接口名称：修改手机号 - 3 保存
     * 接口路径：POST/users/phone
     */
    public ResponseEntity<Object> updatephone(String phone) {
        // 1.根据修改后的手机号码查询，如果手机号码已经存在返回错误信息
        User user = userApi.findByMobile(phone);
        if (user != null) {
            return ResponseEntity.status(500).body(ErrorResult.mobileError());
        }
        User updateUser = UserHolder.get();
        updateUser.setMobile(phone);
        // 3.修改用户
        userApi.update(updateUser);
        return ResponseEntity.ok(null);
    }

    /**
     * 当前用户取消喜欢一个互相关注 移除相互好友记录，添加为粉丝喜欢记录
     *
     * @param
     * @return
     */
    public ResponseEntity<Object> unLike(Long likeId) {
        //移除相互好友记录
        boolean b = friendApi.unFriend(UserHolder.getUserId(), likeId);
        if (b) {
            //原来是好友，添加为粉丝
            UserLike userLike = new UserLike();
            userLike.setId(new ObjectId());
            userLike.setUserId(likeId);
            userLike.setLikeUserId(UserHolder.getUserId());
            userLike.setCreated(System.currentTimeMillis());
            userLikeApi.addFanLike(userLike);
        } else {
            //原来不是好友，直接移除
            userLikeApi.deleteLikeUser(UserHolder.getUserId(), likeId);
        }
        return ResponseEntity.ok(null);
    }
}
